package com.zt.questionnaire.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.NumberFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * Miscellaneous utility methods for number conversion and parsing. Mainly for
 * internal use within the framework; consider Jakarta's Commons Lang for a more
 * comprehensive suite of string utilities.
 *
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @since 1.1.2
 */
public abstract class NumberUtils {

    static Logger log = LoggerFactory.getLogger(NumberUtils.class);

    /**
     * Determine whether the given value String indicates a hex number, i.e. needs
     * to be passed into <code>Integer.decode</code> instead of
     * <code>Integer.valueOf</code> (etc).
     */
    private static boolean isHexNumber(String value) {
        int index = (value.startsWith("-") ? 1 : 0);
        return (value.startsWith("0x", index) || value.startsWith("0X", index) || value.startsWith("#", index));
    }

    /**
     * Decode a {@link BigInteger} from a {@link String} value. Supports
     * decimal, hex and octal notation.
     *
     * @see BigInteger#BigInteger(String, int)
     */
    private static BigInteger decodeBigInteger(String value) {
        int radix = 10;
        int index = 0;
        boolean negative = false;

        // Handle minus sign, if present.
        if (value.startsWith("-")) {
            negative = true;
            index++;
        }

        // Handle radix specifier, if present.
        if (value.startsWith("0x", index) || value.startsWith("0X", index)) {
            index += 2;
            radix = 16;
        } else if (value.startsWith("#", index)) {
            index++;
            radix = 16;
        } else if (value.startsWith("0", index) && value.length() > 1 + index) {
            index++;
            radix = 8;
        }

        BigInteger result = new BigInteger(value.substring(index), radix);
        return (negative ? result.negate() : result);
    }

    /**
     * 向上取整数
     *
     * @param num
     * @return
     */
    public static int getCeil(double num) {
        int i = (int) num;
        if (num - i == 0) {
            return i;
        } else {
            return i + 1;
        }
    }

    /**
     * 向下取整
     *
     * @param num
     * @return
     */
    public static int getFloor(float num) {
        return (int) Math.floor(num);
    }

    /**
     * 向下取整
     *
     * @param num
     * @return
     */
    public static int getFloor(double num) {
        return (int) Math.floor(num);
    }

    /**
     * 获取两个浮点数的和
     *
     * @param f1
     * @param f2
     * @return
     */
    public static Float getFloatSum(Float f1, Float f2) {
        f1 = f1 == null ? 0F : f1;
        f2 = f2 == null ? 0F : f2;
        BigDecimal b1 = new BigDecimal(Float.toString(f1));
        BigDecimal b2 = new BigDecimal(Float.toString(f2));
        return handlerDecimal(b1.add(b2).floatValue(), 2);
    }

    /**
     * 获取两个浮点数的差
     *
     * @param f1
     * @param f2
     * @return
     */
    public static float getFloatSub(Float f1, Float f2) {
        f1 = f1 == null ? 0F : f1;
        f2 = f2 == null ? 0F : f2;
        BigDecimal b1 = new BigDecimal(Float.toString(f1));
        BigDecimal b2 = new BigDecimal(Float.toString(f2));
        return handlerDecimal(b1.subtract(b2).floatValue(), 2);
    }

    /**
     * 向上取整数
     *
     * @param num
     * @return
     */
    public static int getCeil(float num) {
        int i = (int) num;
        if (num - i == 0) {
            return i;
        } else {
            return i + 1;
        }
    }

    /**
     * 保留两位小数，不做任何处理，直接截掉多余的小数
     *
     * @param num
     * @param count
     * @return
     */
    public static float handler(float num, int count) {
        int per = (int) Math.pow(10, count);
        num = num * per;
        int n = (int) num;
        num = (float) n / per;
        return num;
    }

    /**
     * 小数四舍五入保留count位，例如：1.1462保留2位小数后为1.15
     *
     * @param num
     * @param count 小数点后保留几位,0表示四舍五入取整
     * @return
     */
    public static float handlerDecimal(float num, int count) {
        int per = (int) Math.pow(10, count);
        num = num * per;
        int n = Math.round(num);
        num = (float) n / per;
        return num;
    }

    public static double handlerDecimal(double num, int count) {
        double per = (int) Math.pow(10, count);
        num = num * per;
        long n = Math.round(num);
        num = n / per;
        return num;
    }

    /**
     * 根据不同的比例把数值分别分配成相应的数值集合
     *
     * @param totalNum 总数值
     * @param proList  比例集合
     * @return
     */
    public static List<Integer> getNumByPro(int totalNum, List<Integer> proList) {
        List<Integer> list = new ArrayList<Integer>();
        int totalPro = 0;
        for (Integer n : proList) {
            totalPro += n;
        }
        for (int i = 0; i < proList.size(); i++) {
            list.add(totalNum * proList.get(i) / totalPro);
        }
        return list;
    }

    public static void main(String[] args) {
        String js = "[[{\"content\":\"廖\"}],[{\"content\":\"0\"}],[{\"content\":\"32\"}],[{\"content\":\"172\"}],[{\"content\":\"62\"}],[{\"content\":\"失眠\"}],[{}],[{\"content\":\"局部减脂\"},{\"content\":\"改善健康\"}],[{\"content\":\"脸\"},{\"content\":\"肚肚\"}],[{\"content\":\"55\"}],[{}],[{}],[{\"content\":\"1696032000000\"}],[{\"content\":\"60\"}],[{\"content\":\"基因\"},{\"content\":\"口罩原因\"}],[{\"content\":\"饮食营养\"},{\"content\":\"运动\"}],[{\"content\":\"节食\"},{\"content\":\"购买代餐、减脂餐\"}],[{\"content\":\"我曾成功减肥，也曾成功复胖\"},{\"content\":\"我曾坚持过健康饮食运动，但没有明显成效，就又回到了老的习惯\"}],[{\"content\":\"自己做饭\"},{\"content\":\"选择外卖或饭店\"}],[{}],[{}],[{}],[{\"content\":\"没有什么特别\"}],[{}],[{}],[{\"content\":\"3\",\"title\":\"我的工作时间很长，几乎没有工作之外的时间\"},{\"content\":\"1\",\"title\":\"我出差、出行频繁\"},{\"content\":\"2\",\"title\":\"我需要上夜班或跨时区工作\"}],[{\"content\":\"1500000000\"}]]";
        System.out.println(JsonUtils.toList(js, List.class));
        System.out.println(1.22F * 2.22F);
        System.out.println();
        System.out.println(NumberUtils.splitIntList("967,973,974,975,976,977,978,979,980,981,1072,1119,1197,1203,1437,1438,1503,2157,2158,2159,2160,2217,2218,2321,2420,2469,2592,2598,2606,2608,2672,2699,2772,2868,3028", ","));

        System.out.println(getCeil(2.23F));
        System.out.println(getCeil(2.56F));
        System.out.println(getFloor(2.23F));
        System.out.println(getFloor(2.56F));
        System.out.println(getFloor(0F));

        isNumber(null);

        long a = expand10(null, 12);
        System.out.println(a);
        long b = expand10(a, 113);
        System.out.println(b);
        System.out.println(expand10(b, 113));


        System.out.println(getFloatSub(0.12F, 0.03F));
        System.out.println(0.12F + 0.03F);

        System.out.println(handlerDecimal(0.4038623, 3));
        float num = 0.555555555555555555555555555f;

        num = (float) round(num, 5);

        System.out.println(num);

        Object s = 1;
        System.out.println(Number.class.isAssignableFrom(s.getClass()));
        System.out.println(s instanceof Number);
        System.out.println((int) Math.pow(10, 1));
        System.out.println((int) Math.pow(10, 2));
        System.out.println((int) Math.pow(10, 3));
        System.out.println((int) Math.pow(10, 4));
        System.out.println((int) Math.pow(10, 5));
        System.out.println(handlerDecimal(88.93499661624435, 2));
        System.out.println(parseFloat(88.93499661624435f));

//		System.out.println(NumberUtils.handlerDecimal(83/108, 2));
//
//		System.out.println(NumberUtils.handlerDecimal((float)83/108, 2));
//		float a = 100000000;
//		float b = 0.01f;
//		System.out.println(a);
//		 System.out.println(NumberUtils.handlerDecimal((float)533/642, 2));

//		 System.out.println(NumberUtils.handlerDecimal(9.9f, 2));
//		 System.out.println(parseFloat(9.9f));

        double d = 18.449999618530273;
        float f = (float) d;
        System.out.println(d);
        System.out.println(f);
        System.out.println(18.449999618530273f);
        System.out.println(18.149999618530273f);

        System.out.println(Math.round(18.449999618530273));
        System.out.println(Math.round(18.449999618530273f));

        System.out.println(getFloatSub(10f, 20f));
        System.out.println(handlerDecimal(10.46, 0));
        System.out.println(handlerDecimal(10.5, 0));

        BigDecimal w = new BigDecimal(194.2);
        System.out.println(NumberUtils.getCeil(w.floatValue() / 80));

        System.out.println(handler(1.725f, 2));

        System.out.println(round(2.4, 0));
        System.out.println(round(2.5, 0));

        List<Integer> o = new ArrayList<>();
        o.add(1);
        o.add(2);
        o.add(3);
        List<Integer> o1 = new ArrayList<>();
        o1.add(4);
        o1.add(5);
        o1.add(6);
        o.addAll(o1);

//		Iterator<Integer> iterator2 = o.iterator();
//		while (iterator2.hasNext()) {
//				//药方的名称放在最前面
//			System.out.println(iterator2.next());
//			if(o.size() == 6){
//				o.add(0,0);
//				o.add(7);
//			}
//		}


        List<String> list = new ArrayList<>();
        list.add("头痛");
        list.add("发烧");
        list.add("感冒");
        list.add("手疼");
        list.add("脚痛");

        List<List<String>> lists = NumberUtils.groupStrInOne(list);
        System.out.println(JsonUtils.toString(lists));

        System.out.println(round(4.6, 0));

    }

    /**
     * 四舍五入
     *
     * @param num
     * @param n
     * @return
     */
    public static double round(double num, int n) {
        boolean flag = false;
        if (num < 0d) {
            flag = true;
        }

        num = Math.abs(num);

        num = num * Math.pow(10, n);
        num += 0.5d;
        num = (long) num;

        num = num / Math.pow(10d, n);

        if (flag) {
            num = -num;
        }

        return num;
    }

    public static <T extends Number> boolean tryParse(String numstr, RefObject<T> outParam) {
        try {
            if (outParam.argvalue.getClass().equals(Byte.class)) {
                outParam.argvalue = (T) new Byte(Byte.parseByte(numstr));
            } else if (outParam.argvalue.getClass().equals(Short.class)) {
                outParam.argvalue = (T) new Short(Short.parseShort(numstr));
            } else if (outParam.argvalue.getClass().equals(Integer.class)) {
                outParam.argvalue = (T) new Integer(Integer.parseInt(numstr));
            } else if (outParam.argvalue.getClass().equals(Long.class)) {
                outParam.argvalue = (T) new Long(Long.parseLong(numstr));
            } else if (outParam.argvalue.getClass().equals(Float.class)) {
                outParam.argvalue = (T) new Float(Float.parseFloat(numstr));
            } else if (outParam.argvalue.getClass().equals(Double.class)) {
                outParam.argvalue = (T) new Double(Double.parseDouble(numstr));
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static int nullFilter(Integer n) {
        if (n == null) {
            return 0;
        }
        return n;
    }

    public static long nullFilter(Long n) {
        if (n == null) {
            return 0;
        }
        return n;
    }

    public static String nullFilter(String s) {
        if (s == null) {
            return "";
        }
        return s;
    }

    public static int parseInt(String s) {
        if (s == null || "".equals(s)) {
            return 0;
        }
        return Integer.parseInt(s.trim());
    }

    public static long parseLong(String s) {
        if (s == null || "".equals(s)) {
            return 0;
        }
        try {
            return Long.parseLong(s);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return 0;
        }
    }

    public static float parseFloat(String s) {
        if (s == null || "".equals(s)) {
            return 0;
        }
        return Float.parseFloat(s.trim());
    }

    /**
     * 对flot进行处理，小数保留两位(四舍五入)
     *
     * @param money
     * @return
     */
    public static float parseFloat(float money) {
        money = money * 100;
        int n = Math.round(money);
        money = (float) n / 100;
        return money;
    }

    public static double parseFloat(double money) {
        money = money * 100;
        long n = Math.round(money);
        money = (double) n / 100;
        return money;
    }

    /**
     * @param s
     * @return
     */
    public static boolean parseBoolean(String s) {
        if (s == null || "".equals(s)) {
            return false;
        }
        try {
            // 非0为真
            int n = Integer.parseInt(s);
            if (n == 0) {
                return false;
            }
            return true;
        } catch (Exception e) {
            // 不是数字类型
//			log.error(e.getMessage(),e);
        }
        return Boolean.parseBoolean(s);
    }

    /**
     * 循非0为真的原则
     *
     * @param n
     * @return
     */
    public static boolean parseBoolean(Integer n) {
        if (n == null) {
            return false;
        }
        // 非0为真
        if (n == 0) {
            return false;
        }
        return true;
    }

    /**
     * 将以逗号隔开的数字类型的字符串，拆分存放到集合里面，如果不是字符串隔开的格式都返回null
     *
     * @param str   需要拆分的源字符串
     * @param split 用来拆分的标识，例如：,或空格或:等
     * @return
     */
    public static List<Integer> splitIntList(String str, String split) {
        if (str == null || "".equals(str)) {
            return null;
        }

        ArrayList<Integer> list = new ArrayList<>();
        try {
            String[] arry = str.split(split);
            for (String s : arry) {
                if (s == null || "".equals(s)) {
                    continue;
                }
                list.add(NumberUtils.parseInt(s.trim()));
            }
            return list;
        } catch (Exception e) {
            // 客户端参数错误
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 将以逗号隔开的数字类型的字符串，拆分存放到集合里面，如果不是字符串隔开的格式都返回null
     *
     * @param str   需要拆分的源字符串
     * @param split 用来拆分的标识，例如：,或空格或:等
     * @return
     */
    public static List<Long> splitLongList(String str, String split) {
        if (str == null || "".equals(str)) {
            return null;
        }

        ArrayList<Long> list = new ArrayList<>();
        try {
            String[] arry = str.split(split);
            for (String s : arry) {
                if (s == null || "".equals(s)) {
                    continue;
                }
                list.add(NumberUtils.parseLong(s.trim()));
            }
            return list;
        } catch (Exception e) {
            // 客户端参数错误
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 将以逗号隔开的数字类型的字符串，拆分存放到集合里面，如果不是字符串隔开的格式都返回null
     *
     * @param str   需要拆分的源字符串
     * @param split 用来拆分的标识，例如：,或空格或:等
     * @return
     */
    public static List<Float> splitFloatList(String str, String split) {
        if (str == null || "".equals(str)) {
            return null;
        }

        ArrayList<Float> list = new ArrayList<>();
        try {
            String[] arry = str.split(split);
            for (String s : arry) {
                if (s == null || "".equals(s)) {
                    continue;
                }
                list.add(Float.parseFloat(s.trim()));
            }
            return list;
        } catch (Exception e) {
            // 客户端参数错误
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 将以逗号隔开的数字类型的字符串，拆分存放到集合里面，如果不是字符串隔开的格式都返回null
     *
     * @param str   需要拆分的源字符串
     * @param split 用来拆分的标识，例如：,或空格或:等
     * @return
     */
    public static List<String> splitStringList(String str, String split) {
        if (str == null || "".equals(str)) {
            return null;
        }

        ArrayList<String> list = new ArrayList<>();
        try {
            String[] arry = str.split(split);
            for (String s : arry) {
                if (s == null || "".equals(s)) {
                    continue;
                }
                list.add(s.trim());
            }
            return list;
        } catch (Exception e) {
            // 客户端参数错误
            log.error(e.getMessage(), e);
            return null;
        }
    }

    public static <T extends Object> List<T> splitList(String str, String split, Class<T> c) {
        if (str == null || "".equals(str)) {
            return null;
        }

        ArrayList<T> list = new ArrayList<>();
        try {
            String[] arry = str.split(split);
            for (String s : arry) {
                if (s == null || "".equals(s)) {
                    continue;
                }
                Object obj = null;
                if (c.isAssignableFrom(Integer.class)) {
                    obj = Integer.parseInt(s);
                } else if (c.isAssignableFrom(Long.class)) {
                    obj = Long.parseLong(str);
                } else if (c.isAssignableFrom(Float.class)) {
                    obj = Float.parseFloat(s);
                } else if (c.isAssignableFrom(Double.class)) {
                    obj = Double.parseDouble(s);
                } else if (c.isAssignableFrom(Short.class)) {
                    obj = Short.parseShort(str);
                } else if (c.isAssignableFrom(Byte.class)) {
                    obj = Byte.parseByte(str);
                } else {
                    obj = s;
                }
                list.add((T) obj);
            }
            return list;
        } catch (Exception e) {
            // 客户端参数错误
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 将以逗号隔开的数字类型的字符串，拆分存放到集合里面，如果不是字符串隔开的格式都返回null
     *
     * @param str   需要拆分的源字符串
     * @param split 用来拆分的标识，例如：,或空格或:等
     * @return
     */
    public static Set<Long> parseLongSet(String str, String split) {
        if (str == null || "".equals(str)) {
            return null;
        }

        Set<Long> list = new HashSet<>();
        try {
            String[] arry = str.split(split);
            for (String s : arry) {
                if (s == null || "".equals(s)) {
                    continue;
                }
                list.add(NumberUtils.parseLong(s.trim()));
            }
            return list;
        } catch (Exception e) {
            // 客户端参数错误
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 把集合合并成以split隔开的的字符串
     *
     * @param list
     * @param split 用来拆分的标识，例如：,或空格或:等
     * @return
     */
    public static String merge(Collection list, String split) {
        if (list == null || "".equals(list) || list.size() <= 0) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (Object s : list) {
            sb.append(s).append(split);
        }
        // 去掉最后一个空格
        String str = sb.toString().substring(0, sb.length() - 1);
        return str;
    }

    public static boolean isNumber(String str) {
//		Pattern pattern = Pattern.compile("^[0.0-9.0]+$");
        if (str == null) {
            return false;
        }
        Pattern pattern = Pattern.compile("[0.0-9.0]*");
        return pattern.matcher(str).matches();
    }

    /**
     * 计算总和
     *
     * @param list
     * @return
     */
    public static float getSum(List<Float> list) {
        if (list == null || list.size() == 0) {
            return 0;
        }
        float n = 0;
        for (Float f : list) {
            n += f;
        }
        return n;
    }

    /**
     * 获取最大值
     *
     * @param list
     * @return
     */
    public static float getMax(List<Float> list) {
        if (list == null || list.size() == 0) {
            return 0;
        }
        float n = 0;
        for (Float f : list) {
            if (n < f) {
                n = f;
            }
        }
        return n;
    }

    public static <T> List<T> toList(T[] array) {
        if (array == null || array.length == 0) {
            return null;
        }
        List<T> list = Arrays.asList(array);
        return list;
    }

    /**
     * 去除集合里重复的元素，保证元素的唯一性
     *
     * @param list
     * @return
     */
    public static <T> List<T> removeSame(List<T> list) {
        if (list == null || list.size() == 0) {
            return null;
        }
        List<T> list1 = new ArrayList<>();
        for (T t : list) {
            if (!list1.contains(t)) {
                list1.add(t);
            }
        }
        return list1;
    }

    /**
     * 将整数转换为double
     *
     * @param num   所需要转换的数字,保留两位小数
     * @param total 基数
     * @return
     */
    public static Double intToDouble(Integer num, Integer total) {
        if (num == null || total == null || num == 0 || total == 0) {
            return 0d;
        }
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        double n = (double) num / total;
        String result = numberFormat.format(n);
        result = result.replaceAll(",", "");
        return Double.valueOf(result);
    }

    public static Double longToDouble(Long num, Integer total) {
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        double n = (double) num / total;
        String result = numberFormat.format(n);
        result = result.replaceAll(",", "");
        return Double.valueOf(result);
    }

    public static Double floatToDouble(float num, Integer total) {
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        double n = (double) num / total;
        String result = numberFormat.format(n);
        result = result.replaceAll(",", "");
        return Double.valueOf(result);
    }

    public static Double doubleToDouble(double num, Integer total) {
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        double n = (double) num / total;
        String result = numberFormat.format(n);
        result = result.replaceAll(",", "");
        return Double.valueOf(result);
    }

    /**
     * 查找目标值在集合里的区间
     *
     * @param list   起始区间值应该为0，例如：[0,100,200,300]
     * @param target 例如：150，查找150所在的区间，返回值为1
     * @return 如果没有找到，返回-1
     */
    public static int search(List<Integer> list, int target) {
        if (list == null || list.size() == 0) {
            return -1;
        }
        int index = -1;
        int size = list.size();
        for (int i = 0; i < size; i++) {
            int num = list.get(i);
            if (target >= num) {
                index = i;
            } else {
                break;
            }
        }
        return index;
    }

    /**
     * 获取不为空的数
     *
     * @param num
     * @return
     */
    public static int getNotNullNum(Integer num) {
        return num != null ? num : 0;
    }

    public static float getNotNullNum(Float num) {
        return num != null ? num : 0F;
    }

    public static double getNotNullNum(Double num) {
        return num != null ? num : 0D;
    }

    public static long getNotNullNum(Long num) {
        return num != null ? num : 0L;
    }

    /**
     * 把一个数字扩大10倍，为了使数据看起来真实，处理个位数不为0，保证每次拿到的数据不会比上一次小（个位数随机，但是要保证本次比上一次大）
     *
     * @param oldBig 上一次扩大后的数字，0表示不用关心之前的数据
     * @param curr   实际数字，要扩大的数据
     * @return
     */
    public static long expand10(Long oldBig, long real) {
        if (oldBig == null) {
            oldBig = 0L;
        }
        long expand = real * 10;
        int min = 0;
        int max = 9;
        if (oldBig > 0 && real <= oldBig / 10) {
            //正常情况只会等于，不会小于，小于说明传入的参数错误，这里不考虑
//			min = (int) (oldBig % 10)
            //如果数据没有改动，个位数不变，否则按照上面一行的逻辑，多获取几次个位数就一直停留在9上面
            return oldBig;
        }
        expand += RandomUtil.getRandomNum(min, max);
        return expand;
    }

    /**
     * 比较两个float数值的大小，直接比较可能会有误差，参数不能为null
     *
     * @param f1
     * @param f2
     * @return
     */
    public static boolean isSame(float f1, float f2) {
        BigDecimal a = new BigDecimal(String.valueOf(f1));
        BigDecimal b = new BigDecimal(String.valueOf(f2));
        return a.equals(b);
    }

    /**
     * 比较两个double数值的大小，参数不能为null
     *
     * @param f1
     * @param f2
     * @return
     */
    public static boolean isSame(double f1, double f2) {
        BigDecimal a = new BigDecimal(String.valueOf(f1));
        BigDecimal b = new BigDecimal(String.valueOf(f2));
        return a.equals(b);
    }

    /**
     * 将 float转为long
     *
     * @param f
     * @return
     */
    public static long convertLong(Float f) {
        if (f == null) {
            return 0L;
        }
        BigDecimal bd = new BigDecimal(f);
        return bd.longValue();
    }

    /**
     * 求2个数，比例 默认保留2位小数
     *
     * @param t1 分子, 支持数字类型，可以为null
     * @param t2 分母，同上
     * @return
     */
    public static <T1 extends Number, T2 extends Number> float getRatio(T1 t1, T2 t2) {
        return getRatio(t1, t2, 2);
    }


    /**
     * 求2个数比例
     *
     * @param t1    分子, int, long, float 支持
     * @param t2    分母
     * @param count 保留几位小数
     * @return float
     */
    public static <T1 extends Number, T2 extends Number> float getRatio(T1 t1, T2 t2, int count) {
        float ratio = 0F;
        if (t1 == null || t2 == null) {
            return ratio;
        }
        int num1 = t1.intValue();
        int num2 = t2.intValue();
        if (num1 == 0 || num2 == 0) {
            return ratio;
        }
        ratio = (float) num1 / num2;
        return NumberUtils.handlerDecimal(ratio, count);
    }


    /**
     * 对数组进行排列组合。
     * 对数组里的元素进行排列组合（顺序不变，例如：1、2和1、3，但是不会有2、1和3、1）
     *
     * @param list
     * @return
     */
    public static List<List<Integer>> groupInt(List<Integer> list) {
        List<List<Integer>> result = new ArrayList<>();
        LinkedList<Integer> tempList = new LinkedList<Integer>();
        for (int i = 1; i <= list.size(); i++) {
            groupInt(list, i + 1, 0, 0, result, tempList);
        }
        return result;
    }


    /**
     * 对数组里的元素进行排列组合（顺序不变，例如：1、2和1、3，但是不会有2、1和3、1）
     *
     * @param shu  元素
     * @param targ 要选多少个元素，进行组合
     * @param has  当前有多少个元素，递归使用，初始调用者传0
     * @param cur  当前选到的下标，递归使用，初始调用者传0
     *             <p>
     *             1    2   3     //开始下标到2
     *             1    2   4     //然后从3开始
     */
    private static void groupInt(List<Integer> shu, int targ, int has, int cur, List<List<Integer>> result, LinkedList<Integer> tempList) {
        if (targ > shu.size()) {
            return;
        }
        if (has == targ) {
//	            System.out.println(list);
            result.add((List<Integer>) tempList.clone());
        }

        for (int i = cur; i < shu.size(); i++) {
            Integer o = shu.get(i);
            if (!tempList.contains(o)) {
                tempList.add(o);
                groupInt(shu, targ, has + 1, i, result, tempList);
                tempList.removeLast();
            }
        }

    }


    /**
     * 对数组进行排列组合。
     * 对数组里的元素进行排列组合（顺序不变，例如：1、2和1、3，但是不会有2、1和3、1）
     *
     * @param list
     * @return
     */
    public static List<List<String>> groupStr(List<String> list) {
        List<List<String>> result = new ArrayList<>();
        LinkedList<String> tempList = new LinkedList<String>();
        for (int i = 1; i <= list.size(); i++) {
            groupStr(list, i + 1, 0, 0, result, tempList);
        }
        return result;
    }

    /**
     * 对数组进行排列组合。每个元素也单独放到集合里面
     * 对数组里的元素进行排列组合（顺序不变，例如：1、2和1、3，但是不会有2、1和3、1）。
     *
     * @param list
     * @return
     */
    public static List<List<String>> groupStrInOne(List<String> list) {
        List<List<String>> result = new ArrayList<>();
        LinkedList<String> tempList = new LinkedList<String>();
        for (int i = 1; i <= list.size(); i++) {
            groupStr(list, i + 1, 0, 0, result, tempList);
        }
        for (String s : list) {
            List<String> lt = new ArrayList<>();
            lt.add(s);
            result.add(0, lt);
        }
        return result;
    }


    /**
     * 对数组里的元素进行排列组合（顺序不变，例如：1、2和1、3，但是不会有2、1和3、1）
     *
     * @param shu  元素
     * @param targ 要选多少个元素，进行组合
     * @param has  当前有多少个元素，递归使用，初始调用者传0
     * @param cur  当前选到的下标，递归使用，初始调用者传0
     *             <p>
     *             1    2   3     //开始下标到2
     *             1    2   4     //然后从3开始
     */
    private static void groupStr(List<String> shu, int targ, int has, int cur, List<List<String>> result, LinkedList<String> tempList) {
        if (targ > shu.size()) {
            return;
        }
        if (has == targ) {
//	            System.out.println(list);
            result.add((List<String>) tempList.clone());
        }

        for (int i = cur; i < shu.size(); i++) {
            String o = shu.get(i);
            if (!tempList.contains(o)) {
                tempList.add(o);
                groupStr(shu, targ, has + 1, i, result, tempList);
                tempList.removeLast();
            }
        }

    }

}
